﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Lucene.Net.Analysis;
using PanGu;
using Lucene.Net.Analysis.PanGu;
using Lucene.Net.Search;
using Lucene.Net.QueryParsers;
using Lucene.Net.Index;

namespace RFSerchComponent
{

    public static class Searcher
    {
        //单索引
        private static IndexReader indexReader;

        //多索引
        private static IndexReader indexReader1;
        private static IndexReader indexReader2;

        static public List<string> SplitKeyWords(string keywords, Analyzer analyzer)
        {
            System.IO.StreamReader reader = new System.IO.StreamReader(PanGu.Framework.Stream.WriteStringToStream(keywords,
                Encoding.UTF8), Encoding.UTF8);

            TokenStream tokenStream = analyzer.TokenStream("", reader);

            global::Lucene.Net.Analysis.Token token = tokenStream.Next();

            List<string> result = new List<string>();

            while (token != null)
            {
                result.Add(keywords.Substring(token.StartOffset(), token.EndOffset() - token.StartOffset()));
                token = tokenStream.Next();
            }

            return result;

        }

        static public string GetKeyWordsSplitBySpace(string keywords, PanGuTokenizer ktTokenizer)
        {
            StringBuilder result = new StringBuilder();

            ICollection<WordInfo> words = ktTokenizer.SegmentToWordInfos(keywords);

            foreach (WordInfo word in words)
            {
                if (word == null)
                {
                    continue;
                }

                result.AppendFormat("{0}^{1}.0 ", word.Word, (int)Math.Pow(3, word.Rank));
            }

            return result.ToString().Trim();
        }

        /// <summary>
        /// 执行查询
        /// </summary>
        /// <param name="indexDir">索引所在路径</param>
        /// <param name="q">关键字</param>
        /// <param name="pageLen">每页项数</param>
        /// <param name="pageNo">页号</param>
        /// <param name="recCount">结果个数</param>
        /// <returns>结果集合</returns>
        public static List<TNews> SearchResult(String indexDir, String q, int pageLen, int pageNo, out int recCount)
        {
            try
            {
                string keywords = q;

                //获取indexReader
                if (indexReader == null)
                {
                    indexReader = IndexReader.Open(indexDir);
                }

                else
                {
                    if (!indexReader.IsCurrent())
                    {
                        indexReader = indexReader.Reopen();
                    }
                }

                IndexSearcher search = new IndexSearcher(indexReader);
                q = GetKeyWordsSplitBySpace(q, new PanGuTokenizer());

                //需要查询的字段
                /*
                1.	附件名
                2.	功能名称
                3.	备注
                4.	创建时间
                5.	附件内容
                */

                QueryParser queryParser = new QueryParser("title", new PanGuAnalyzer(true));
                Query titleQuery = queryParser.Parse(q);
                titleQuery.SetBoost(1.5f);

                queryParser = new QueryParser("function", new PanGuAnalyzer(true));
                Query functionQuery = queryParser.Parse(q);
                functionQuery.SetBoost(1.3f);

                queryParser = new QueryParser("remark", new PanGuAnalyzer(true));
                Query remarkQuery = queryParser.Parse(q);
                remarkQuery.SetBoost(1.1f);

                queryParser = new QueryParser("content", new PanGuAnalyzer(true));
                Query contentQuery = queryParser.Parse(q);

                BooleanQuery bq = new BooleanQuery();
                bq.Add(titleQuery, BooleanClause.Occur.SHOULD);
                bq.Add(functionQuery, BooleanClause.Occur.SHOULD);
                bq.Add(remarkQuery, BooleanClause.Occur.SHOULD);
                bq.Add(contentQuery, BooleanClause.Occur.SHOULD);

                Hits hits = search.Search(bq);

                List<TNews> result = new List<TNews>();

                recCount = hits.Length();
                int i = (pageNo - 1) * pageLen;

                while (i < recCount && result.Count < pageLen)
                {
                    TNews news = null;

                    try
                    {
                        news = new TNews();
                        news.AttID = hits.Doc(i).Get("id");
                        news.OrgDB = hits.Doc(i).Get("db");

                        //PanGu.HighLight.SimpleHTMLFormatter simpleHTMLFormatter =
                        //    new PanGu.HighLight.SimpleHTMLFormatter("<font color=\"red\">", "</font>");

                        //PanGu.HighLight.Highlighter highlighter =
                        //    new PanGu.HighLight.Highlighter(simpleHTMLFormatter,
                        //    new Segment());

                        //highlighter.FragmentSize = 50;

                        //news.Abstract = highlighter.GetBestFragment(keywords, news.Content);
                        //news.TitleHighLighter = highlighter.GetBestFragment(keywords, news.Title);
                        //if (string.IsNullOrEmpty(news.TitleHighLighter))
                        //{
                        //    news.TitleHighLighter = news.Title;
                        //}
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e.Message);
                    }
                    finally
                    {
                        result.Add(news);
                        i++;
                    }
                }

                search.Close();
                return result;

            }
            catch (Exception ex)
            {
                recCount = 0;
                return new List<TNews>();
            }
        }

        #region 执行多索引查询-废弃
        /// <summary>
        /// 执行多索引查询
        /// </summary>
        /// <param name="indexDir1">索引1所在路径</param>
        /// <param name="indexDir2">索引2所在路径</param>
        /// <param name="q">关键字</param>
        /// <param name="type">大类型（全部=1、收文发文=2、新闻=3）,可为空</param>
        /// <param name="function">子分类名称，可为空</param>
        /// <param name="pageLen">每页项数</param>
        /// <param name="pageNo">页号</param>
        /// <param name="recCount">结果个数</param>
        /// <returns>结果集合</returns>

        //public static List<TNews> SearchResultInMutiIndex(String indexDir1, string indexDir2, String q, string type, string function, int pageLen, int pageNo, out int recCount)
        //{
        //    string keywords = q;
        //    List<TNews> results = new List<TNews>();
        //    Lucene.Net.Search.Searcher searcher = null;

        //    try
        //    {
        //        try
        //        {
        //            if (indexReader1 == null)
        //            {
        //                indexReader1 = IndexReader.Open(indexDir1);
        //            }
        //            else
        //            {
        //                if (!indexReader1.IsCurrent())
        //                {
        //                    indexReader1 = indexReader1.Reopen();
        //                }
        //            }
        //        }
        //        catch (Exception ex)
        //        { }

        //        try
        //        {
        //            if (indexReader2 == null)
        //            {
        //                indexReader2 = IndexReader.Open(indexDir2);
        //            }
        //            else
        //            {
        //                if (!indexReader2.IsCurrent())
        //                {
        //                    indexReader2 = indexReader2.Reopen();
        //                }
        //            }
        //        }
        //        catch (Exception ex)
        //        { }

        //        if (indexReader1 == null && indexReader2 == null)
        //        {
        //            recCount = 0;
        //            return results;
        //        }
        //        else if (indexReader1 != null && indexReader2 != null)
        //        {
        //            IndexSearcher[] searchers = new IndexSearcher[2];
        //            searchers[0] = new IndexSearcher(indexReader1);
        //            searchers[1] = new IndexSearcher(indexReader2);
        //            searcher = new MultiSearcher(searchers);
        //        }
        //        else if (indexReader1 != null && indexReader2 == null)
        //        {
        //            searcher = new IndexSearcher(indexReader1);
        //        }

        //        else if (indexReader1 == null && indexReader2 != null)
        //        {
        //            searcher = new IndexSearcher(indexReader2);
        //        }

        //        //构建

        //        q = GetKeyWordsSplitBySpace(q, new PanGuTokenizer());

        //        //需要查询的字段
        //        /*
        //        1.	附件名
        //        2.	功能名称
        //        3.	备注
        //        4.	创建时间
        //        5.	附件内容
        //        6. 
        //        */

        //        QueryParser queryParser = new QueryParser("title", new PanGuAnalyzer(true));
        //        Query titleQuery = queryParser.Parse(q);
        //        titleQuery.SetBoost(1.5f);


        //        queryParser = new QueryParser("remark", new PanGuAnalyzer(true));
        //        Query remarkQuery = queryParser.Parse(q);
        //        remarkQuery.SetBoost(1.1f);

        //        queryParser = new QueryParser("content", new PanGuAnalyzer(true));
        //        Query contentQuery = queryParser.Parse(q);

        //        BooleanQuery bq = new BooleanQuery();
        //        BooleanQuery bq2 = new BooleanQuery();
        //        bq.Add(titleQuery, BooleanClause.Occur.SHOULD);
        //        //  bq.Add(functionQuery, BooleanClause.Occur.SHOULD);
        //        bq.Add(remarkQuery, BooleanClause.Occur.SHOULD);
        //        bq.Add(contentQuery, BooleanClause.Occur.SHOULD);
        //        RangeFilter filter = null;

        //        //大分类
        //        if (!string.IsNullOrEmpty(type))
        //        {
        //            if (type == SearchType.Attach || type == SearchType.News || type == SearchType.NewsColumn)
        //            {
        //                queryParser = new QueryParser("type", new PanGuAnalyzer(true));
        //                Query typeQuery = queryParser.Parse(type);
        //                bq2.Add(bq, BooleanClause.Occur.MUST);
        //                bq2.Add(typeQuery, BooleanClause.Occur.MUST);
        //            }
        //            else
        //            {
        //                bq2 = bq;
        //            }
        //            //filter = new RangeFilter("type", type, type, true, true);
        //        }
        //        else
        //        {
        //            bq2 = bq;
        //        }

        //        //小分类
        //        if (!string.IsNullOrEmpty(function))
        //        {
        //            queryParser = new QueryParser("function", new PanGuAnalyzer(true));
        //            Query functionSQuery = queryParser.Parse(function);
        //            bq2.Add(functionSQuery, BooleanClause.Occur.MUST);
        //        }
        //        //else
        //        //{
        //        //    queryParser = new QueryParser("function", new PanGuAnalyzer(true));
        //        //    Query functionQuery = queryParser.Parse(q);
        //        //    functionQuery.SetBoost(1.3f);
        //        //    bq2.Add(functionQuery, BooleanClause.Occur.SHOULD);
        //        //}

        //        Hits hits = searcher.Search(bq2, filter);

        //        List<TNews> result = new List<TNews>();

        //        recCount = hits.Length();
        //        int i = (pageNo - 1) * pageLen;

        //        while (i < recCount && result.Count < pageLen)
        //        {
        //            TNews news = null;

        //            try
        //            {
        //                news = new TNews();
        //                news.AttID = hits.Doc(i).Get("id");
        //                news.OrgDB = hits.Doc(i).Get("db");
        //                news.Abstract = hits.Doc(i).Get("abstracts");
        //                news.Type = hits.Doc(i).Get("type");

        //            }
        //            catch (Exception e)
        //            {
        //                Console.WriteLine(e.Message);
        //            }
        //            finally
        //            {
        //                result.Add(news);
        //                i++;
        //            }
        //        }

        //        searcher.Close();
        //        return result;
        //    }
        //    catch (Exception ex)
        //    {
        //        recCount = 0;
        //        return results;
        //    }
        //}
        #endregion

        /// <summary>
        /// 使用多索引返回查询结果，并分页
        /// </summary>
        /// <param name="indexDir1">索引1所在路径</param>
        /// <param name="indexDir2">索引2所在路径</param>
        /// <param name="q">查询关键字</param>
        /// <param name="functions">小分类列表</param>
        /// <param name="startDay">开始日期</param>
        /// <param name="endDay">结束日期</param>
        /// <param name="pageLen">每页显示项目数</param>
        /// <param name="pageNo">当前页</param>
        /// <param name="recCount">查询记录总数</param>
        /// <returns></returns>
        public static List<TNews> SearchResultInMutiIndex(String indexDir1, string indexDir2, String q, string[] functions, string startDay, string endDay, int pageLen, int pageNo, out int recCount)
        {
            string keywords = q;
            List<TNews> results = new List<TNews>();
            Lucene.Net.Search.Searcher searcher = null;

            try
            {
                try
                {
                    if (indexReader1 == null)
                    {
                        indexReader1 = IndexReader.Open(indexDir1);
                    }
                    else
                    {
                        if (!indexReader1.IsCurrent())
                        {
                            indexReader1 = indexReader1.Reopen();
                        }
                    }
                }
                catch (Exception ex)
                { }

                try
                {
                    if (indexReader2 == null)
                    {
                        indexReader2 = IndexReader.Open(indexDir2);
                    }
                    else
                    {
                        if (!indexReader2.IsCurrent())
                        {
                            indexReader2 = indexReader2.Reopen();
                        }
                    }
                }
                catch (Exception ex)
                { }

                if (indexReader1 == null && indexReader2 == null)
                {
                    recCount = 0;
                    return results;
                }
                else if (indexReader1 != null && indexReader2 != null)
                {
                    IndexSearcher[] searchers = new IndexSearcher[2];
                    searchers[0] = new IndexSearcher(indexReader1);
                    searchers[1] = new IndexSearcher(indexReader2);
                    searcher = new MultiSearcher(searchers);
                }
                else if (indexReader1 != null && indexReader2 == null)
                {
                    searcher = new IndexSearcher(indexReader1);
                }

                else if (indexReader1 == null && indexReader2 != null)
                {
                    searcher = new IndexSearcher(indexReader2);
                }

                //构建

                q = GetKeyWordsSplitBySpace(q, new PanGuTokenizer());

                //需要查询的字段
                /*
                1.	附件名
                2.	功能名称
                3.	备注
                4.	创建时间
                5.	附件内容
                6. 
                */

                QueryParser queryParser = new QueryParser("title", new PanGuAnalyzer(true));
                Query titleQuery = queryParser.Parse(q);
                titleQuery.SetBoost(1.5f);

                queryParser = new QueryParser("remark", new PanGuAnalyzer(true));
                Query remarkQuery = queryParser.Parse(q);
                remarkQuery.SetBoost(1.1f);

                queryParser = new QueryParser("content", new PanGuAnalyzer(true));
                Query contentQuery = queryParser.Parse(q);



                // RangeQuery query = new RangeQuery(new Term("time", "20060101"), new Term("time","20060130"), true);

                BooleanQuery bq = new BooleanQuery();
                BooleanQuery bqFunction = new BooleanQuery();
                BooleanQuery bq2 = new BooleanQuery();
                bq.Add(titleQuery, BooleanClause.Occur.SHOULD);
                //  bq.Add(functionQuery, BooleanClause.Occur.SHOULD);
                bq.Add(remarkQuery, BooleanClause.Occur.SHOULD);
                bq.Add(contentQuery, BooleanClause.Occur.SHOULD);
                RangeFilter filter = null;

                //查询内容应该属于functions列出的功能。
                if (functions != null && functions.Length > 0)
                {
                    Query functionQuery;
                    for (int j = 0; j < functions.Length; j++)
                    {
                        queryParser = new QueryParser("function", new PanGuAnalyzer(true));
                        functionQuery = queryParser.Parse(functions[j]);
                        bqFunction.Add(functionQuery, BooleanClause.Occur.SHOULD);
                    }
                    bq2.Add(bq, BooleanClause.Occur.MUST);
                    bq2.Add(bqFunction, BooleanClause.Occur.MUST);
                }
                else
                {
                    bq2 = bq;
                }

                //日期过滤
                if (!string.IsNullOrEmpty(startDay) && !string.IsNullOrEmpty(endDay))
                {
                    filter = new RangeFilter("createTime", startDay, endDay, true, true);
                }

                Hits hits = searcher.Search(bq2, filter);

                List<TNews> result = new List<TNews>();

                recCount = hits.Length();
                int i = (pageNo - 1) * pageLen;

                while (i < recCount && result.Count < pageLen)
                {
                    TNews news = null;

                    try
                    {
                        news = new TNews();
                        news.AttID = hits.Doc(i).Get("id");
                        news.OrgDB = hits.Doc(i).Get("db");
                        news.Abstract = hits.Doc(i).Get("abstracts");
                        news.Type = hits.Doc(i).Get("type");
                        news.Function = hits.Doc(i).Get("function");

                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e.Message);
                    }
                    finally
                    {
                        result.Add(news);
                        i++;
                    }
                }

                searcher.Close();
                return result;
            }
            catch (Exception ex)
            {
                recCount = 0;
                return results;
            }
        }

        /// <summary>
        /// 使用多索引返回全部查询结果
        /// </summary>
        /// <param name="indexDir1">索引1所在路径</param>
        /// <param name="indexDir2">索引2所在路径</param>
        /// <param name="q">查询关键字</param>
        /// <param name="functions">小分类列表</param>
        /// <param name="startDay">开始日期</param>
        /// <param name="endDay">结束日期</param>
        /// <param name="recCount">查询记录总数</param>
        /// <returns></returns>
        public static List<TNews> SearchResultInMutiIndex(String indexDir1, string indexDir2, String q, string[] functions, string startDay, string endDay, out int recCount)
        {
            string keywords = q;
            List<TNews> results = new List<TNews>();
            Lucene.Net.Search.Searcher searcher = null;

            try
            {
                try
                {
                    if (indexReader1 == null)
                    {
                        indexReader1 = IndexReader.Open(indexDir1);
                    }
                    else
                    {
                        if (!indexReader1.IsCurrent())
                        {
                            indexReader1 = indexReader1.Reopen();
                        }
                    }
                }
                catch (Exception ex)
                { }

                try
                {
                    if (indexReader2 == null)
                    {
                        indexReader2 = IndexReader.Open(indexDir2);
                    }
                    else
                    {
                        if (!indexReader2.IsCurrent())
                        {
                            indexReader2 = indexReader2.Reopen();
                        }
                    }
                }
                catch (Exception ex)
                { }

                if (indexReader1 == null && indexReader2 == null)
                {
                    recCount = 0;
                    return results;
                }
                else if (indexReader1 != null && indexReader2 != null)
                {
                    IndexSearcher[] searchers = new IndexSearcher[2];
                    searchers[0] = new IndexSearcher(indexReader1);
                    searchers[1] = new IndexSearcher(indexReader2);
                    searcher = new MultiSearcher(searchers);
                }
                else if (indexReader1 != null && indexReader2 == null)
                {
                    searcher = new IndexSearcher(indexReader1);
                }

                else if (indexReader1 == null && indexReader2 != null)
                {
                    searcher = new IndexSearcher(indexReader2);
                }

                //构建

                q = GetKeyWordsSplitBySpace(q, new PanGuTokenizer());

                //需要查询的字段
                /*
                1.	附件名
                2.	功能名称
                3.	备注
                4.	创建时间
                5.	附件内容
                6. 
                */

                QueryParser queryParser = new QueryParser("title", new PanGuAnalyzer(true));
                Query titleQuery = queryParser.Parse(q);
                titleQuery.SetBoost(1.5f);

                queryParser = new QueryParser("remark", new PanGuAnalyzer(true));
                Query remarkQuery = queryParser.Parse(q);
                remarkQuery.SetBoost(1.1f);

                queryParser = new QueryParser("content", new PanGuAnalyzer(true));
                Query contentQuery = queryParser.Parse(q);

                BooleanQuery bq = new BooleanQuery();
                BooleanQuery bqFunction = new BooleanQuery();
                BooleanQuery bq2 = new BooleanQuery();
                bq.Add(titleQuery, BooleanClause.Occur.SHOULD);
                bq.Add(remarkQuery, BooleanClause.Occur.SHOULD);
                bq.Add(contentQuery, BooleanClause.Occur.SHOULD);
                RangeFilter filter = null;

                //查询内容应该属于functions列出的功能。
                if (functions != null && functions.Length > 0)
                {
                    Query functionQuery;
                    for (int j = 0; j < functions.Length; j++)
                    {
                        queryParser = new QueryParser("function", new PanGuAnalyzer(true));
                        functionQuery = queryParser.Parse(functions[j]);
                        bqFunction.Add(functionQuery, BooleanClause.Occur.SHOULD);
                    }
                    bq2.Add(bq, BooleanClause.Occur.MUST);
                    bq2.Add(bqFunction, BooleanClause.Occur.MUST);
                }
                else
                {
                    bq2 = bq;
                }

                //日期过滤
                if (!string.IsNullOrEmpty(startDay) && !string.IsNullOrEmpty(endDay))
                {
                    filter = new RangeFilter("createTime", startDay, endDay, true, true);
                }

                Hits hits = searcher.Search(bq2, filter);

                List<TNews> result = new List<TNews>();

                recCount = hits.Length();
                int i = 0;

                while (i < recCount)
                {
                    TNews news = null;

                    try
                    {
                        news = new TNews();
                        news.AttID = hits.Doc(i).Get("id");
                        news.OrgDB = hits.Doc(i).Get("db");
                        news.Abstract = hits.Doc(i).Get("abstracts");
                        news.Type = hits.Doc(i).Get("type");

                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e.Message);
                    }
                    finally
                    {
                        result.Add(news);
                        i++;
                    }
                }

                searcher.Close();
                return result;
            }
            catch (Exception ex)
            {
                recCount = 0;
                return results;
            }
        }
    }
}
